package main

import (
	"fmt"
	"math/rand"
	"sync"
	"sync/atomic"
	"time"
)

func main() {
	//testAtomic()
	testAtomicValue()
}

func testAtomic() {
	var count int64 = 23

	//Load 方法会取出 addr 地址中的值
	println(atomic.LoadInt64(&count))    //23
	println(atomic.AddInt64(&count, 1))  //24
	println(atomic.AddInt64(&count, -1)) //23

	//比较和替换
	println(atomic.CompareAndSwapInt64(&count, 23, 25)) //true
	println(atomic.LoadInt64(&count))                   //25
	println(atomic.CompareAndSwapInt64(&count, 23, 25)) //false
	println(atomic.LoadInt64(&count))                   //25

	//替换
	println(atomic.SwapInt64(&count, 100)) //25
	println(atomic.LoadInt64(&count))      //100

	//Store 方法会把一个值存入到指定的 addr 地址中
	atomic.StoreInt64(&count, 101)
	println(atomic.LoadInt64(&count)) //101
}

// testAtomicValue
//
//	@Description: atomic.Value。它可以原子地存取对象类型，但也只能存取，不能 CAS 和 Swap
func testAtomicValue() {
	//将配置放入 atomic.Value 中
	var config atomic.Value
	config.Store(loadNewConfig())
	var cond = sync.NewCond(&sync.Mutex{})

	go func() {
		for {
			time.Sleep(time.Duration(5+rand.Int63n(5)) * time.Second)
			config.Store(loadNewConfig())
			//广播 广播唤醒所有的等待者，谁调用wait谁就是等待者
			cond.Broadcast()
		}
	}()

	go func() {

		for {
			cond.L.Lock()
			cond.Wait()
			c := config.Load().(Config)
			fmt.Println("load new Config: ", c)
			cond.L.Unlock()

		}

	}()
	select {}
}

type Config struct {
	NodeName string
	CreateAt time.Time
}

func loadNewConfig() Config {
	return Config{
		NodeName: "node1",
		CreateAt: time.Now(),
	}
}
